package monitori_di_hoare;

import semafori.SemaforoBinario;
import semafori.SemaforoBinarioAPriorita;

public final class Monitor {
	private SemaforoBinario mutex = new SemaforoBinario(1);
	private SemaforoBinario urgent = new SemaforoBinario(0);
	private int urgentcount = 0;

	public void Enter() {
		mutex.P();
	}// Enter

	public void Exit() {
		if (urgentcount > 0)
			urgent.V();
		else
			mutex.V();
	}// Exit

	public Condition newCondition() {
		return new ConditionVariable();

	}

	private class ConditionVariable implements Condition {

		private SemaforoBinario xsem = new SemaforoBinario(0);
		private int xcount = 0;

		public void Wait() {
			xcount++;

			if (urgentcount > 0)
				urgent.V();
			else
				mutex.V();
			xsem.P();
			xcount--;
		}// Wait

		public void Signal() {
			if (xcount > 0) {
				urgentcount++;
				xsem.V();
				urgent.P();
				urgentcount--;
			}
		}// Signal
	}

	public ConditionP newConditionP() {
		return new ConditionVariablePriorited();
	}

	private class ConditionVariablePriorited implements ConditionP {
		private SemaforoBinarioAPriorita xsem = new SemaforoBinarioAPriorita(0);
		private int xcount = 0;

		public void Wait(int priority) {
			xcount++;
			if (urgentcount > 0)
				urgent.V();
			else
				mutex.V();
			xsem.P(priority);
			xcount--;
		}// Wait

		public void Signal() {
			if (xcount > 0) {
				urgentcount++;
				xsem.V();
				urgent.P();
				urgentcount--;
			}
		}// Signal
	}// ConditionVariablePriorited
}// Monitor

